package so.sao.code.service.domain.entity;

import java.time.LocalDateTime;
import java.time.format.DateTimeFormatter;
import java.util.ArrayList;
import java.util.List;
import java.util.Set;

import javax.persistence.Convert;
import javax.persistence.Entity;
import javax.persistence.EntityListeners;
import javax.persistence.FetchType;
import javax.persistence.JoinColumn;
import javax.persistence.OneToMany;
import javax.persistence.Version;

import org.apache.commons.lang3.time.DateFormatUtils;
import org.springframework.data.jpa.domain.support.AuditingEntityListener;
import org.springframework.http.HttpStatus;

import lombok.Data;
import so.sao.code.service.domain.entity.tagbatch.DefaultTagBatch;
import so.sao.code.service.domain.entity.tagbatch.DuplicateTagBatch;
import so.sao.code.service.domain.entity.tagbatch.PackageTagBatch;
import so.sao.code.service.domain.entity.tagbatch.RollTagBatch;
import so.sao.code.service.domain.entity.tagbatch.WrapTagBatch;
import so.sao.code.service.infrastructure.dozer.Mapper;
import so.sao.code.service.infrastructure.enums.CodeMessage;
import so.sao.code.service.infrastructure.enums.TAG_BATCH_STATUS;
import so.sao.code.service.infrastructure.enums.TAG_BATCH_TYPE;
import so.sao.code.service.infrastructure.jpa.convert.TagBatchStatusConvert;
import so.sao.code.service.infrastructure.jpa.convert.TagBatchTypeConvert;
import so.sao.top.core.util.rest.RestException;

/**
 * 标签批次信息表
 *
 * @author cuijunhua
 */

@Data
@Entity
@EntityListeners(AuditingEntityListener.class)
public class TagBatch extends BaseEntity {

	/**
	 *
	 */
	private static final long serialVersionUID = 5134552803666287169L;

	/**
	 * 批次名称
	 */
	private String name = "";
	/**
	 * 该批次标签数量
	 */
	private Long tagCount = 0L;
	/**
	 * 批次类型，参照so.sao.code.enums.TagBatchType
	 */
	@Convert(converter = TagBatchTypeConvert.class)
	private TAG_BATCH_TYPE type = TAG_BATCH_TYPE.NORMAL;
	/**
	 * 批次状态
	 */
	@Convert(converter = TagBatchStatusConvert.class)
	private TAG_BATCH_STATUS status = TAG_BATCH_STATUS.UNACTIVATE;
	/**
	 * 码段可用信息表id<-- lookup_table.id 该表中存储预先配置的标签可用码段信息，依据sub_domain进行配置的
	 */
	private Long lookupId = 0L;
	/**
	 * 标签批次起始序号
	 */
	private Long seqnumStart = 0L;
	/**
	 * 标签批次结束序号
	 */
	private Long seqnumEnd = 0L;
	/**
	 * 企业id
	 */
	private Long eseId = 0L;
	/**
	 * 顶级企业id：用于按顶级企业统计发码量，以便判断该企业或其子企业生成的码量有没有超过限制
	 */
	private Long masterEseId = 0L;
	/**
	 * 标签批次印刷格式id<--tag_batch_config.id
	 * <p>
	 * 复用印刷格式
	 */
	private Long tagBatchConfigId = 0L;
	/**
	 * 二维码域名
	 * <p>
	 * 与子域名联合决定二维码数据被存放到哪个库里
	 */
	private String domain = "";
	/**
	 * 二维码子域名
	 * <p>
	 * 用于决定用哪个密码生成二维码加密串
	 */
	private String subDomain = "";
	/**
	 * 该批次分卷数量，套标套数，批量生成时的批次数量
	 */
	private Integer unitCount = 0;
	/**
	 * 每卷／每套／批量时每批标签数量
	 */
	private Long unitTagCount = 0L;
	/**
	 * 冗余量，百分比
	 */
	private Float redundancy = 0F;
	/**
	 * 套标比例数 1:ratio
	 */
	private Integer ratio = 0;
	/**
	 * 双码或多码个数，默认为双码，即2
	 */
	private Integer duplicate = 0;
	/**
	 * 请求来源，例如portal、isv或者供应链
	 */
	private String source = "portal";
	/**
	 * 印刷文件状态
	 */
	private Integer printFileStatus = 0;
	/**
	 * 印刷文件压缩密码
	 */
	private String zipPassword = "";

	/**
	 * 标签长度
	 */
	private Integer codeLength = 0;
	/**
	 * 版本号
	 */
	@Version
	private Integer version = 0;

	private String fileName = "";
	@OneToMany(fetch = FetchType.LAZY)
	@JoinColumn(name = "tagBatchId")
	private Set<RangeActivation> ranges;

	public String createFileName() {
		if (fileName == null || fileName.equals("")) {
			fileName = String.join("/", eseId.toString(), DateFormatUtils.format(getCreateDate(), "yyyy/MM/dd"),
					DateTimeFormatter.ofPattern("yyyyMMddHHmmss").format(LocalDateTime.now()), name + ".zip");
		}
		return fileName;
	}

	public String getSeqnumFileName() {
		return String.join("/", eseId.toString(), DateFormatUtils.format(getCreateDate(), "yyyy/MM/dd"),
				"SEQNUM_" + getId().toString() + ".zip");
	}

	public TagBatch become() {
		switch (type) {
		case NORMAL:
		case THIRDPARTYCODE:
			return Mapper.map(this, DefaultTagBatch.class);
		case ROLL:
			return Mapper.map(this, RollTagBatch.class);
		case PACKAGE:
			return Mapper.map(this, PackageTagBatch.class);
		case DUPLICATE:
			return Mapper.map(this, DuplicateTagBatch.class);
		case WRAP:
			return Mapper.map(this, WrapTagBatch.class);
		default:
			throw null;
		}
	}

	public long computeTotalTagCount() {
		return unitCount * tagCount
				+ unitCount * Double.valueOf(Math.ceil(tagCount * redundancy / 100) + "").longValue();
	}

	public List<TagBatch> convertToList() {
		List<TagBatch> tagBatches = new ArrayList<>();
		tagBatches.add(Mapper.map(this, TagBatch.class));
		return tagBatches;
	}

	// 检查批次格式是否设置
	public TagBatch checkTagBatchConfig() {
		if (getTagBatchConfigId() == null || getTagBatchConfigId().longValue() == 0) {
			throw new RestException(HttpStatus.BAD_REQUEST, CodeMessage.TagBatchConfigNotSet);
		}
		return this;
	}

}
